package cn.zhxu.toys.msg;

import java.util.HashMap;
import java.util.Map;

/**
 * 动态消息发送器（用于多租户模式）
 * @author Troy.Zhou
 * @since 0.0.3
 */
public class DynamicMsgSender implements MsgSender {

    /** 消息发送器池，一个平台一个 */
    private final Map<Object, AbstractMsgSender> senderPool = new HashMap<>();

    private final Object lock = new Object();

    /** 路由配置器 */
    private RoutingConfigurer routingConfigurer;

    /** 消息发送器工厂 */
    private SenderFactory senderFactory;


    public interface RoutingConfigurer {

        /**
         * 感知当前平台的主键标识
         * @return 当前租户的主键标识
         */
        Object determineCurrentLookupKey();

        /**
         * 获取当前平台的消息发送器的初始化参数
         * @param lookupKey 当前租户的主键标识
         * @return 初始化参数
         */
        Map<String, String> getInitParams(Object lookupKey);

        /**
         * 获取当前平台的消息模板
         * @param lookupKey 当前租户的主键标识
         * @param tmplName 模板名称
         * @return 模板值
         */
        MsgTemplate getTemplate(Object lookupKey, String tmplName);

    }

    /**
     * 消息发送器工厂
     */
    public interface SenderFactory {

        /**
         * 创建一个消息发送器
         * @param lookupKey 当前租户的主键标识 @since v0.5.0
         * @return 消息发送器
         */
        AbstractMsgSender create(Object lookupKey);

    }

    @Override
    public String name() {
        Object key = routingConfigurer.determineCurrentLookupKey();
        MsgSender sender = senderPool.get(key);
        return sender != null ? sender.name() : "Unknow";
    }

    @Override
    public SendResult send(String phone, String tmplName, String... tmplArgs) {
        Object key = routingConfigurer.determineCurrentLookupKey();
        AbstractMsgSender sender;
        MsgTemplate template;
        synchronized (lock) {
            sender = senderPool.get(key);
            if (sender == null) {
                sender = senderFactory.create(key);
                if (sender == null) {
                    return SendResult.fail("未能创建消息发送器");
                }
                sender.init(routingConfigurer.getInitParams(key));
                senderPool.put(key, sender);
            }
            // 模板名称不用拼上租户标识，因为 sender 已经是租户隔离了
            template = sender.getMsgTemplate(tmplName);
            if (template == null) {
                template = routingConfigurer.getTemplate(key, tmplName);
                if (template == null) {
                    return SendResult.fail("未获取到消息模板：" + tmplName);
                }
                template.setName(tmplName);
                sender.addMsgTemplate(template);
            }
        }
        return sender.send(phone, template, tmplArgs);
    }

    public void clearPool() {
        synchronized (lock) {
            senderPool.clear();
        }
    }

    public RoutingConfigurer getRoutingConfigurer() {
        return routingConfigurer;
    }

    public void setRoutingConfigurer(RoutingConfigurer routingConfigurer) {
        this.routingConfigurer = routingConfigurer;
    }

    public SenderFactory getSenderFactory() {
        return senderFactory;
    }

    public void setSenderFactory(SenderFactory senderFactory) {
        this.senderFactory = senderFactory;
    }

}
